package zdream.pmfield;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import zdream.pmfield.core.PLogger;
import zdream.pmfield.core.Result;
import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.MoveTarget;
import zdream.pmfield.data.foe.MoveTargetType;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.StageWrapper;
import zdream.pmfield.stage.action.AttackAction;
import zdream.pmfield.stage.message.ActionRequestMessage;
import zdream.pmfield.stage.message.ActionRequestReply;
import zdream.pmfield.stage.message.StageMessage;
import zdream.pmfield.stage.object.FoeActor;
import zdream.pmfield.stage.object.Seat;
import zdream.pmfield.stage.object.StageMove;
import zdream.pmfield.storage.FoeTemplateStorage;

/**
 * test 请使用: mvn test -Dtest=Main -DskipTests=false
 *
 * @author Zdream
 * @date 2023-03-16
 * @since 0.0.1
 */
public class Main {

	public static void main(String[] args) {
		Instant a = Instant.now();
		PLogger.info("Main", a.toString());

		Main m = new Main();
		m.run();
	}

	Scanner scanner;
	StageWrapper wrapper;
	FoeTemplateStorage storage;

	public Main() {
		scanner = new Scanner(System.in);

		storage = new FoeTemplateStorage();
		storage.load();
	}

	public void run() {
		final MoveTemplate move = storage.findMoveById(1, 1);
		final MoveTemplate move22 = storage.findMoveById(22, 1);

		final Foe foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(20)
				.withMove(move)
				.build();

		final Foe foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(20)
				.withMove(move22)
				.build();

		wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.buildWrapper();
		wrapper.onDefaultActionRequest(foe2);
		wrapper.printBeforeHandleMessage();

		for (int i = 0; i < 100; i++) {
			final StageMessage message = wrapper.runUntilNext();
			if (message == null) {
				break;
			}
			try {
				Thread.sleep(500);
			} catch (InterruptedException ignored) {}

			if (message instanceof ActionRequestMessage) {
				waitForReply((ActionRequestMessage) message);
			}
		}
	}

	StageMove selectMove;


	private void waitForReply(ActionRequestMessage request) {
		final FoeActor foe = request.foe;
		if (foe.side != 1) {
			return;
		}

		List<StageMove> moves = new ArrayList<>(foe.attackMoves);
		moves.addAll(foe.stageMoves);
		StageMove[] array = moves.toArray(new StageMove[0]);
		ActionRequestReply reply = request.createReplyTemplate();

		while (true) {
			System.out.println("\n\n选择使用的技能:");
			for (int index = 0; index < array.length; index++) {
				System.out.printf("<%d> %s%n", index, array[index]);
			}
			System.out.print(">>> ");

			// 等待输入
			final String input = scanner.nextLine();
			int selectedIndex;
			try {
				selectedIndex = Integer.parseInt(input);
				selectMove = array[selectedIndex];
			} catch (RuntimeException e) {
				System.out.println("错误的输入: " + input);
				continue;
			}

			System.out.println("你选择了: " + selectMove);
			final boolean success = waitForTarget(reply.withMove(selectMove));
			if (success) {
				break;
			} else {
				final AttackAction action = reply.action.asAttack();
				action.move = null;
			}
		}

		final Result result = reply.commit();
		if (!result.success) {
			System.out.println("选择出现问题: " + result.errorMessage);
		}
		System.out.println("\n\n");
	}

	private boolean waitForTarget(ActionRequestReply reply) {
		final StageMove move = reply.action.asAttack().move;
		final MoveTarget target = move.target;

		if (target.type == MoveTargetType.SELF) {
			return confirm(reply);
		}

		if (target.type == MoveTargetType.ENEMY) {
			return waitForEnemyTarget(reply, target);
		}
		return waitForSeatTarget(reply, target);
	}

	private boolean waitForEnemyTarget(ActionRequestReply reply, MoveTarget target) {
		System.out.println("\n\n------");
		System.out.println(wrapper.stage);
		System.out.println("------");
		System.out.println("选择技能目标:");

		final FoeActor[] array = wrapper.stage.allFoes.stream()
				.filter(foe -> foe != reply.message.foe)
				.toArray(FoeActor[]::new);
		for (int index = 0; index < array.length; index++) {
			System.out.printf("<%d> %s%n", index, array[index]);
		}
		System.out.print(">>> ");

		// 等待输入
		final String input = scanner.nextLine();
		int selectedIndex;
		try {
			selectedIndex = Integer.parseInt(input);
			reply.withTarget(array[selectedIndex]);
		} catch (RuntimeException e) {
			System.out.println("回退");
			return false;
		}

		return confirm(reply);
	}

	private boolean waitForSeatTarget(ActionRequestReply reply, MoveTarget target) {
		System.out.println("\n\n------");
		System.out.println(wrapper.stage);
		System.out.println("------");
		System.out.println("选择技能目标:");

		for (Seat seat : wrapper.stage.seats) {
			System.out.printf("<%d> %s%n", seat.x, seat);
		}
		System.out.print(">>> ");

		// 等待输入
		final String input = scanner.nextLine();
		int selectedX;
		try {
			selectedX = Integer.parseInt(input);
			reply.withTarget(wrapper.stage.findSeatByX(selectedX));
		} catch (RuntimeException e) {
			System.out.println("回退");
			return false;
		}

		return confirm(reply);
	}

	private boolean confirm(ActionRequestReply reply) {
		System.out.println("\n\n------");
		wrapper.attackChecker.checkAttackAction(reply.action.asAttack());
		System.out.println("------");
		System.out.println("是否确认? 确认按回车, 输入任何文字则回退");
		System.out.print(">>> ");

		// 等待输入
		final String input = scanner.nextLine();
		return input.length() == 0;
	}
}
